Bug 6068

Bug Description:

This is a race.
From line 208 to line 221 at groovy.util.AntBuilder(groovy 1.7.9), System.in is saved and assigned and then restored without any synchronization:
More details about this bug are at GROOVY-6068 JIRA page.

Interleaving Description:

groovy.util.AntBuilder:

t1 t2 protected void nodeCompleted(final Object parent, final Object node) {
...
1 3 InputStream savedIn = System.in;
InputStream savedProjectInputStream = project.getDefaultInputStream();
if (!(savedIn instanceof DemuxInputStream)) {
project.setDefaultInputStream(savedIn);
2 System.setIn(new DemuxInputStream(project));
}

try {
lastCompletedNode = performTask(task);
} finally {
// restore original streams
project.setDefaultInputStream(savedProjectInputStream);
4 5 System.setIn(savedIn);
}
...
}

a) thread 1 saves its original System.in at 1.
b) thread 1 set its System.in a new DemuxInputStream at 2.
c) context switched, thread 2 saves its original System.in which is the DemuxInputStream in step b) at 3.
d) context switched , thread 1 restores its orginal System.in at 4.
e) context switched, thread 2 restores its orignal System.in which is the new DemuxInputStream in step b) at 5.
f) the new DemuxInputStream in step b) is supposed to be cleared by GC, but now is referenced by System.in and causes a memory leak.

How To Reproduce:

This bug is reproduced under groovy 1.7.9 and JDK 1.6.0_33.
Execute the following scripts to run the test to reproduce the bug (assume the location of the groovy test project is groovy_test_home).

Linux:
${groovy_test_home}/scripts/run6068.sh [--threadnum arg] [--loops arg]
Windows:
%groovy_test_home%\scripts\run6068.bat [--threadnum arg] [--loops arg]

The default argument values will be taken if not specified. For example,
${groovy_test_home}/scripts/run6068.sh
is the same as
${groovy_test_home}/scripts/run6068.sh --threadnum 2 --loops 10

Option Function Default Value Valid Values
--threadnum,-tn thread number 2 integer
--loops,-l loops number 10 integer